<?php 

class PdoMysql{

	public static $config = array(

				'DB_HOST'     =>     'localhost',     //数据库地址
				'DB_USER'     =>     'root',          //数据库用户名
				'DB_PASSWD'   =>     '',              //数据库密码
				'DB_NAME'     =>     '',              //数据库名
				'DB_TYPE'     =>     'mysql',         //数据库类型  
				'DB_PORT'	  =>     '3306',          //数据库端口
				'DB_CHARSET'  =>     'UTF-8',         //字符集类型
				'DB_PREFIX'   =>     '',              //表前缀

		);
	private static $link = null;                  //连接对象
	public static $pconnect = false;             //是否开启长连接
	public static $dbVersion = '';               //版本信息
	public static $connected = false;             //连接是否成功
	private static $PDOStatement = null;           //PDOStatement对象
	public static $querySqlStr = '';               //最后执行的SQL语句
	public static $lastInsertId = '';              //最后执行的成功的ID
	public static $NumRows = '';                   //执行受影响的条数

	public function __construct ($dbConfig = '') {
		//通过判断pdo类是否存在验证是否开启PDO扩展
		if (!class_exists("PDO")) {
			self::error_info("不支持PDO，请开启扩展");
		}
		//初始化配置项
		if (is_array($dbConfig)) {
			self::$config = array_merge(self::$config,$dbConfig);
		}

		//连接配置项
		if(empty(self::$config['params']))self::$config['params'] = array();
		//判断连接是否存在
		if (!isset(self::$link)) {

			$configs = self::$config;
			
			//开启长连接
			if(self::$pconnect){
				$configs['params'][constant("PDO::ATTR_PERSISTENT")] = true;
			}

			try{
				//实例化PDO连接
				self::$link = new PDO($configs['DB_TYPE'].':host='.$configs['DB_HOST'].';dbname='.$configs['DB_NAME'],$configs['DB_USER'],$configs['DB_PASSWD'],$configs['params']);

			}catch(PDOException $e){
				self::error_info($e->getMessage);
			}
			//如果没有连接成功则抛出错误信息
			if (!self::$link) {
				self::error_info('数据库连接出错！');
				return false;
			}
			//设置字符集类型
			self::$link->exec('SET NAMES '.$configs['DB_CHARSET']);
			//获取数据库版本信息
			self::$dbVersion = self::$link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));

			//设置连接成功
			self::$connected = true;

			unset($configs);
		}

	}
	/**
	 * [getAll 查询全部数据]
	 * @param  [string] $sql [sql语句]
	 * @return [array]      [description]
	 */
	public static function getAll ( $sql = null ) {
		if ($sql != null) {
			self::query($sql);
		}
		$result = self::$PDOStatement->fetchAll(constant("PDO::FETCH_ASSOC"));
		return $result;
	}
	/**
	 * [getRow 查询单条数据]
	 * @param  [string] $sql [查询语句]
	 * @return [array]      [description]
	 */
	public static function getRow($sql = null){
		if ($sql != null) {
			self::query($sql);
		}
		$result = self::$PDOStatement->fetch(constant("PDO::FETCH_ASSOC"));
		return $result;
	}
	/**
	 * [findById 根据索引查询]
	 * @param  [string] $tabName [表名]
	 * @param  [int] $byid    [索引值]
	 * @param  string $fields  [插叙内容]
	 * @return [array]          [description]
	 */
	public static function findById ($tabName,$byid,$fields = '*') {

		$tabName = self::reTableName($tabName);

		$sql = "SELECT %s FROM %s where id = %d";
		return self::getRow(sprintf($sql,self::parseFields($fields),$tabName,$byid));
	}

	/**
	 * [find 条件查询]
	 * @param  [string] $tabName [表名]
	 * @param  [string OR array] $where   [条件]
	 * @param  string $fields  [查询内容]
	 * @param  [type] $order   [排序]
	 * @param  [type] $limit   [查询条数]
	 * @param  [type] $group   [分组]
	 * @param  [type] $having  [二次筛选]
	 * @return [array]          [description]
	 */
	public static function find($tabName,$where=null,$fields='*',$order=null,$limit=null,$group=null,$having=null){
		$tabName = self::reTableName($tabName);

		$sql = "SELECT ".self::parseFields($fields)." FROM ".$tabName
		.self::parseWhere($where)
		.self::parseGroup($group)
		.self::parseHaving($having)
		.self::parseOrder($order)
		.self::parseLimit($limit);
		$dataAll = self::getAll($sql);
		if (count($dataAll) == 1) {
			$result = $dataAll[0];
		}else{
			$result = $dataAll;
		}

		return $result;
	}
	/**
	 * [add 增加操作]
	 * @param [string] $tabName [description]
	 * @param [array] $data    [description]
	 * @return [int]
	 */
	public static function add ($tabName,$data) {

		$tabName = self::reTableName($tabName);

		//提取数组key作为字段
		$keys = array_keys($data);
		array_walk($keys,array('PdoMysql','addSpecialChar'));
		$keysStr = join(",",$keys);

		//提取键值作为字段值
		$values = array_values($data);
		$valuesStr = "'".join("','",$values)."'";

		//组成新的sql
		$sql = "INSERT INTO {$tabName}({$keysStr}) VALUES({$valuesStr})";

		return self::excute($sql);
	}
	/**
	 * [addAll 插入多条数据]
	 * @param [string] $tabName [表名]
	 * @param [array] $data    [数据]
	 */
	public static function addAll ($tabName,$data) {

		$tabName = self::reTableName($tabName);

		$keys = array_keys($data[0]);
		array_walk($keys,array('PdoMysql','addSpecialChar'));
		$keysStr = join(",",$keys);

		$valuesStr = '';

		foreach($data as $key=>$value){
			$str = array_values($value);
			$valuesStr .= "('".join("','",$str)."'),";
		}
		$valuesStr = rtrim($valuesStr,",");

		$sql = "INSERT INTO {$tabName}({$keysStr}) VALUES{$valuesStr}";
		return self::excute($sql);

	} 
	/**
	 * [update 更新]
	 * @param  [string] $tabName [表名]
	 * @param  [array] $data    [更新内容]
	 * @param  [array OR string] $where   [条件]
	 * @param  [string] $order   [description]
	 * @param  [array OR string] $limit   [description]
	 * @return [int]          [description]
	 */
	public static function update ($tabName,$data,$where=null,$order=null,$limit=null) {

		$tabName = self::reTableName($tabName);

		$valuesStr = '';
		foreach ($data as $key=>$value) {
			$valuesStr .= $key."='".$value."',";
		}
		$valuesStr = rtrim($valuesStr,",");

		$sql = "UPDATE {$tabName} set {$valuesStr} ".self::parseWhere($where).self::parseOrder($order).self::parseLimit($limit);

		return self::excute($sql);
	}
	/**
	 * [delete 删除]
	 * @param  [string] $tabName [表名]
	 * @param  [array OR string] $where   [description]
	 * @param  [string] $order   [description]
	 * @param  [string] $limit   [description]
	 * @return [int]          [description]
	 */
	public static function delete ($tabName,$where,$order=null,$limit=null) {
		$tabName = self::reTableName($tabName);
		
		$sql = "DELETE FROM {$tabName} ".self::parseWhere($where).self::parseOrder($order).self::parseLimit($limit);

		return self::excute($sql);
	}
	/**
	 * [getLastId 获取最后插入的ID]
	 * @return [int] [description]
	 */
	public static function getLastId () {
		$link = self::$link;
		if (!$link)return false;

		return self::$lastInsertId;
	}
	/**
	 * [getSqlStr 获取最后执行的sql语句]
	 * @return [string] [description]
	 */
	public static function getSqlStr () {
		$link = self::$link;
		if (!$link)return false;

		return self::$querySqlStr;
	}
	/**
	 * [getDbVersion 获取数据库版本号]
	 * @return [type] [description]
	 */
	public static function getDbVersion () {
		$link = self::$link;
		if (!$link)return false;

		return self::$dbVersion;
	}
	/**
	 * [getShowTable 获取数据库中的所有表]
	 * @return [type] [description]
	 */
	public static function getShowTable(){
		$tables = array();
		if (self::query("SHOW TABLES")) {
			$result = self::getAll();
			foreach ($result as $key=>$value) {
				$tables[$key] = current($value);
			}
		}

		return $tables;
	}
	/**
	 * [close 销毁连接对象]
	 * @return [type] [description]
	 */
	public static function close () {
		self::$link = null;
	} 
	/**
	 * [reTableName 给表加前缀]
	 * @param  [string] $tabName [description]
	 * @return [string]          [description]
	 */
	private static function reTableName ($tabName) {
		return self::$config['DB_PREFIX'].$tabName;
	}

	/**
	 * [parseLimit 重组limit]
	 * @param  [array OR string OR int] $limit [description]
	 * @return [string]        [description]
	 */
	private static function parseLimit($limit){
		$limitStr = '';
		if (is_array($limit)) {
			if(count($limit) > 1){
				$limitStr .= " LIMIT ".$limit[0].",".$limit[1];
			}else{
				$limitStr .= " LIMIT ".$limit[0];
			}
		}elseif ((is_string($limit) && $limit != '') || is_numeric($limit)) {
			$limitStr .= " LIMIT ".$limit;
		}

		return empty($limitStr) ? '' : $limitStr;	
	}

	/**
	 * [parseOrder 重组order by]
	 * @param  [array OR string] $order [description]
	 * @return [string]        [description]
	 */
	private static function parseOrder($order){
		$orderStr = '';
		if (is_string($order) && $order != '') {
			$orderStr .= " ORDER BY ".$order;
		}elseif(is_array($order)){
			$orderStr .= " ORDER BY ".implode(",",$order);
		}

		return empty($orderStr) ? '' : $orderStr;
	}

	/**
	 * [parseHaving 对分组结果进行二次having筛选]
	 * @param  [string] $having [description]
	 * @return [string]         [description]
	 */
	private static function parseHaving($having) {
		$havingStr = '';
		if (is_string($having) && $having != '') {
			$havingStr .= " HAVING ".$having;
		}

		return empty($havingStr) ? '' : $havingStr;
	}

	/**
	 * [parseGroup 重组 GROUP BY]
	 * @param  [array OR string] $group [description]
	 * @return [string]        [description]
	 */
	private static function parseGroup($group){
		$groupStr = '';
		if (is_array($group)) {
			$groupStr .= " GROUP BY ".implode(",",$group);
		}elseif (is_string($group) && $group != '') {
			$groupStr .= " GROUP BY ".$group;
		}
		return empty($groupStr) ? '' : $groupStr;
	}

	/**
	 * [parseWhere 重组where]
	 * @param  [type] $where [description]
	 * @return [type]        [description]
	 */
	private static function parseWhere($where){
		if(is_array($where)){
			$whereStr = self::parseArrToStr($where);
		}elseif(is_string($where) && !empty($where)){
			$whereStr = $where;
		}

		return empty($whereStr) ? '' : ' WHERE '.$whereStr;
	}
	/**
	 * [parseArrToStr 重组查询条件]
	 * @param  [array] $arr [description]
	 * @return [string]      [description]
	 */
	private static function parseArrToStr ($arr) {
		$whereStr = '';
		if (is_array($arr)) {
			foreach ($arr as $key => $value) {
				$whereStr .= " ".$key ."='".$value."' AND";
			}
			$whereStr = substr($whereStr,0,-3);
		}
		return $whereStr;
	}
	/**
	 * [parseFields 解析字段]
	 * @param  [array,string] $fields [description]
	 * @return [string]         [description]
	 */
	private static function parseFields ($fields) {
		if (is_array($fields)) {
			//使用回调对$fields添加“｀”
			array_walk($fields,array('PdoMysql','addSpecialChar'));
			//将数组以“，”拆分成字符串
			$fieldStr = implode(",",$fields);
		}elseif(is_string($fields) && $fields != ''){
			//如果是字符串并且不为空
			if (strpos($fields,"`") === false) {
				$fields = explode(",",$fields);
				array_walk($fields,array('PdoMysql','addSpecialChar'));
				$fieldStr = implode(",",$fields);
			}else{
				$fieldStr = $fields;
			}

		}else{
			$fieldStr = "*";
		}
		return $fieldStr;
	}

	/**
	 * [addSpecialChar 通过反引号引用字段]
	 * @param [type] &$value [description]
	 */
	private static function addSpecialChar(&$value){
		if (strpos($value,'`') === false && $value != '*') {
			$value = "`".$value."`";
		}
		return $value;
	}

	/**
	 * [excute 操作增、删、改]
	 * @param  [string] $sql [description]
	 * @return [int]      [返回受影响的条数]
	 */
	public static function excute ($sql = null) {

		$link = self::$link;
		if(!$link) return false;
		self::$querySqlStr = $sql;
		if(!empty(self::$PDOStatement)) return self::free();

		$result = $link->exec(self::$querySqlStr);
		
		self::haveError();

		if ($result) {
			//保存最后执行成功的ID
			self::$lastInsertId = $link->lastInsertId();

			//保存受影响的条数
			self::$NumRows = $result;
			return self::$NumRows;
		}else{
			return false;
		}
	}

	/**
	 * [query 执行查询]
	 * @param  string $sql [description]
	 * @return [array]      [description]
	 */
	private static function query ($sql = '') {
		$link = self::$link;
		//如果没有连接对象则直接退出
		if(!$link) return false;
		//如果$PDOStatement存在 则销毁
		if(!empty(self::$PDOStatement)) self::free();
		//保存执行的SQL语句
		self::$querySqlStr = $sql;
		//准备要执行的查询
		self::$PDOStatement = $link->prepare(self::$querySqlStr);
		//执行预处理语句
		$result = self::$PDOStatement->execute();

		//错误信息
		self::haveError();
		return $result;
	}
	/**
	 * [haveError 执行中抛出错误信息]
	 * @return [type] [description]
	 */
	private static function haveError(){
		$obj = empty(self::$PDOStatement) ? self::$link : self::$PDOStatement;
		$arrError = $obj->errorInfo();
		//如果存在错误则抛出错误信息
		if ($arrError[0] != '00000') {
			$str = "SQLSTATE: ".$arrError[0]."<br />SQL ERROR: ".$arrError[2]."<br />SQL: ".self::$querySqlStr;
			self::error_info($str);
			return false;
		}
		if (!self::$querySqlStr) {
			self::error_info('没有可执行的SQL语句');
			return false;
		}
	}
	/**
	 * [free 销毁PDOStatement对象]
	 * @return [type] [description]
	 */
	private static function free () {
		self::$PDOStatement = null;
	}

	/**
	 * [error_info 错误提示]
	 * @param  [string] $info [错误信息]
	 * @return [string]       [description]
	 */
	public static function error_info($info) {
		echo "<div style='width:80%;background-color:#CD5C5C;color:black;font-size:18px;padding:10px 10px;'>{$info}<div>";

	}



}